package com.nulldev.util.networking.async2.tcp.listeners.packets;

import java.util.concurrent.RejectedExecutionException;

import com.nulldev.util.networking.async2.events.ManualResetEvent;
import com.nulldev.util.networking.async2.tcp.listeners.TCPClientConnection;

public final class MessageCollectorTCPClientConnectionPacket implements Runnable {

	public final ManualResetEvent fDone = new ManualResetEvent(false);
	private final TCPClientConnection fClient;
	private final byte[] fData;
	private MessageCollectorTCPClientConnectionPacket fPreviousPacket;
	public boolean fCancel = false;

	/**
	 * Constructs a new (incoming) message collector packet.
	 *
	 * Use this class to receive data from a client. This is an incoming message
	 * that will remain in the servers thread pool as a job for the thread pool
	 * workers.
	 *
	 * @param client         is the packets TCPClientConnection.
	 * @param data           is the string received.
	 * @param previousPacket is the previous message collector packet of the
	 *                       TCPClientConnection.
	 */
	public MessageCollectorTCPClientConnectionPacket(TCPClientConnection client, byte[] data, MessageCollectorTCPClientConnectionPacket previousPacket) {
		fClient = client;
		fData = data;
		fPreviousPacket = previousPacket;

		sendToThreadPool();
	}

	protected void sendToThreadPool() {
		try {
			fClient.fServer.fMyThreadPool.execute(this);
		} catch (RejectedExecutionException ex) {
			fClient.forceDisconnect();
		}
	}

	/**
	 * Cancel this message collector packet.
	 *
	 * By calling this method this and all the previous message collector packets
	 * that are stored in the thread pool will be canceled. Call this method for the
	 * last message collector of the TCPClientConnection when the
	 * TCPClientConnection disconnects.
	 *
	 */
	public void cancel() {
		fCancel = true;
		fDone.set();
	}

	@Override
	public void run() {
		try {
			if (fPreviousPacket == null) {
				fClient.fMyMessageCollector.appendData(fData);
			} else {
				fPreviousPacket.fDone.waitOne();

				if (!fCancel && !fPreviousPacket.fCancel) {
					fClient.fMyMessageCollector.appendData(fData);
				} else {
					fCancel = true;
				}

				fPreviousPacket = null;
			}
		} catch (Exception ex) {
		}

		fDone.set();
	}

}